// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   AbstractClassGenerator.java

package org.springframework.cglib.core;

import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.*;
import org.springframework.asm.ClassReader;

// Referenced classes of package org.springframework.cglib.core:
//			ClassGenerator, DefaultGeneratorStrategy, DefaultNamingPolicy, NamingPolicy, 
//			GeneratorStrategy, ClassNameReader, ReflectUtils, CodeGenerationException, 
//			Predicate

public abstract class AbstractClassGenerator
	implements ClassGenerator
{
	protected static class Source
	{

		String name;
		Map cache;

		public Source(String name)
		{
			cache = new WeakHashMap();
			this.name = name;
		}
	}


	private static final Object NAME_KEY = new Object();
	private static final ThreadLocal CURRENT = new ThreadLocal();
	private GeneratorStrategy strategy;
	private NamingPolicy namingPolicy;
	private Source source;
	private ClassLoader classLoader;
	private String namePrefix;
	private Object key;
	private boolean useCache;
	private String className;
	private boolean attemptLoad;

	protected AbstractClassGenerator(Source source)
	{
		strategy = DefaultGeneratorStrategy.INSTANCE;
		namingPolicy = DefaultNamingPolicy.INSTANCE;
		useCache = true;
		this.source = source;
	}

	protected void setNamePrefix(String namePrefix)
	{
		this.namePrefix = namePrefix;
	}

	protected final String getClassName()
	{
		if (className == null)
			className = getClassName(getClassLoader());
		return className;
	}

	private String getClassName(ClassLoader loader)
	{
		final Set nameCache = getClassNameCache(loader);
		return namingPolicy.getClassName(namePrefix, source.name, key, new Predicate() {

			public boolean evaluate(Object arg)
			{
				return nameCache.contains(arg);
			}

		});
	}

	private Set getClassNameCache(ClassLoader loader)
	{
		return (Set)((Map)source.cache.get(loader)).get(NAME_KEY);
	}

	public void setClassLoader(ClassLoader classLoader)
	{
		this.classLoader = classLoader;
	}

	public void setNamingPolicy(NamingPolicy namingPolicy)
	{
		if (namingPolicy == null)
			namingPolicy = DefaultNamingPolicy.INSTANCE;
		this.namingPolicy = namingPolicy;
	}

	public NamingPolicy getNamingPolicy()
	{
		return namingPolicy;
	}

	public void setUseCache(boolean useCache)
	{
		this.useCache = useCache;
	}

	public boolean getUseCache()
	{
		return useCache;
	}

	public void setAttemptLoad(boolean attemptLoad)
	{
		this.attemptLoad = attemptLoad;
	}

	public boolean getAttemptLoad()
	{
		return attemptLoad;
	}

	public void setStrategy(GeneratorStrategy strategy)
	{
		if (strategy == null)
			strategy = DefaultGeneratorStrategy.INSTANCE;
		this.strategy = strategy;
	}

	public GeneratorStrategy getStrategy()
	{
		return strategy;
	}

	public static AbstractClassGenerator getCurrent()
	{
		return (AbstractClassGenerator)CURRENT.get();
	}

	public ClassLoader getClassLoader()
	{
		ClassLoader t = classLoader;
		if (t == null)
			t = getDefaultClassLoader();
		if (t == null)
			t = getClass().getClassLoader();
		if (t == null)
			t = Thread.currentThread().getContextClassLoader();
		if (t == null)
			throw new IllegalStateException("Cannot determine classloader");
		else
			return t;
	}

	protected abstract ClassLoader getDefaultClassLoader();

	protected Object create(Object key)
	{
		Class gen = null;
		Source source1 = source;
		JVM INSTR monitorenter ;
		ClassLoader loader;
		Map cache2;
		Object save;
		loader = getClassLoader();
		cache2 = null;
		cache2 = (Map)source.cache.get(loader);
		if (cache2 == null)
		{
			cache2 = new HashMap();
			cache2.put(NAME_KEY, new HashSet());
			source.cache.put(loader, cache2);
		} else
		if (useCache)
		{
			Reference ref = (Reference)cache2.get(key);
			gen = (Class)(ref != null ? ref.get() : null);
		}
		if (gen != null)
			break MISSING_BLOCK_LABEL_284;
		save = CURRENT.get();
		CURRENT.set(this);
		Object obj;
		this.key = key;
		if (attemptLoad)
			try
			{
				gen = loader.loadClass(getClassName());
			}
			catch (ClassNotFoundException e) { }
		if (gen == null)
		{
			byte b[] = strategy.generate(this);
			String className = ClassNameReader.getClassName(new ClassReader(b));
			getClassNameCache(loader).add(className);
			gen = ReflectUtils.defineClass(className, b, loader);
		}
		if (useCache)
			cache2.put(key, new WeakReference(gen));
		obj = firstInstance(gen);
		CURRENT.set(save);
		return obj;
		Exception exception;
		exception;
		CURRENT.set(save);
		throw exception;
		source1;
		JVM INSTR monitorexit ;
		  goto _L1
		Exception exception1;
		exception1;
		throw exception1;
_L1:
		return firstInstance(gen);
		RuntimeException e;
		e;
		throw e;
		e;
		throw e;
		e;
		throw new CodeGenerationException(e);
	}

	protected abstract Object firstInstance(Class class1)
		throws Exception;

	protected abstract Object nextInstance(Object obj)
		throws Exception;

}
